home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / Sherlock 2.0 / DevLibSrc / Main_DevLib / LIBio.c < prev    next >
Text File  |  1995-11-16  |  9KB  |  489 lines

  1. /*
  2.     devlib: ANSI Standard i/o module:  this module calls only ANSI Standard functions.
  3.  
  4.     source:  LIBio.c
  5.     started: November 4, 1993.
  6.     version:
  7.         November 8, 1995.
  8.             Replaced error with err_error1-4.
  9.         July 10, 1994.
  10.             Added io_remove, io_rename, io_seek, io_write_buffer.
  11.             Added io_read_pad_all.
  12. */
  13. #include <LIBlib.h>
  14.  
  15. #include <LIBio.h>
  16. #include <LIBmem.h>
  17. #include <LIBobj.h>
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22.  
  23. /*
  24.     Define the size of the buffers allocated by io_create.
  25. */
  26. #define IO_BUF_SIZE 1024
  27.  
  28. /*
  29.     The file status.
  30. */
  31. typedef enum { IO_NULL, IO_CLOSED, IO_INPUT, IO_OUTPUT, IO_EOF } dummy;
  32.  
  33. /*
  34.     Define global statistics variables.
  35. */
  36. long io_read_chars = 0;        /* Chars read by io_read and io_read_all. */
  37. long io_write_chars = 0;    /* Chars written by io_write. */
  38. long io_nl_count = 1;        /* TRUE: number of consecutive newlines output. */
  39.  
  40. /*
  41.     Prototypes for local routines.
  42. */
  43. static char *     io_cvt_status    (int status);
  44.  
  45. /*
  46.     Allocate a block of n bytes using lib_calloc.
  47. */
  48. static void *
  49. io_alloc(size_t n)
  50. {
  51.     void * p = NULL;
  52.  
  53.     /* Align. */
  54.     if (n & 1) {
  55.         n++;
  56.     }
  57.  
  58.     p = lib_calloc( (size_t) 1, n);
  59.  
  60.     if (p == NULL) {
  61.         char buf [100];
  62.         cvt_long(buf, 100, n);
  63.         err_fatal3("io_alloc: can not allocate ", buf, " bytes.");
  64.     }
  65.  
  66.     return p;
  67. }
  68.  
  69. /*
  70.     Close a file opened with io_open() or io_create().
  71.     Closing a NULL file is OK.
  72. */
  73. void
  74. io_close(io_file * file)
  75. {
  76.     FTAG("io_close");
  77.     STATB(ftag);
  78.  
  79.     if (file) {
  80.  
  81.         ASSERT(
  82.             file -> io_file_path_name &&
  83.                 (file -> io_file_status == IO_INPUT ||
  84.                  file -> io_file_status == IO_OUTPUT ||
  85.                  file -> io_file_status == IO_EOF));
  86.  
  87.         /* Flush an output file. */
  88.         if (file -> io_file_status == IO_OUTPUT && file -> io_file_count > 0) {
  89.             io_write(file);
  90.         }
  91.  
  92.         fclose(file -> io_file_file);
  93.  
  94.         if (file -> io_file_buffer) {
  95.             lib_free(file -> io_file_buffer);
  96.         }
  97.  
  98.         lib_free(file);
  99.     }
  100.  
  101.     STATX(ftag);
  102. }
  103.  
  104. /*
  105.     Open the file for writing only.
  106.     Return an io_file or NULL.
  107. */
  108. io_file *
  109. io_create(char * path_name, bool cant_flag, bool text_flag)
  110. {
  111.     FTAG("io_create");
  112.     FILE * os_file = NULL;
  113.     io_file * file = NULL;
  114.     STATB(ftag);
  115.     ASSERT(path_name);
  116.  
  117.     if (path_name[0] == '\0') {
  118.         if (cant_flag) {
  119.             err_error1("io_create: NULL file name");
  120.         }
  121.         STATX(ftag);
  122.         return NULL;
  123.     }
  124.  
  125.     os_file = fopen(path_name, text_flag ? "w" : "wb");
  126.     if (os_file == NULL) {
  127.         if (cant_flag) {
  128.             err_error2("Can not create ", path_name);
  129.         }
  130.         STATX(ftag);
  131.         return NULL;
  132.     }
  133.  
  134.     file = io_alloc(sizeof(io_file));
  135.  
  136.     file -> io_file_path_name = path_name;
  137.     file -> io_file_file = os_file;
  138.     file -> io_file_status = IO_OUTPUT;
  139.     file -> io_file_buffer = io_alloc(IO_BUF_SIZE);
  140.     file -> io_file_bufsize = IO_BUF_SIZE;
  141.     file -> io_file_pointer = file -> io_file_buffer;
  142.     file -> io_file_count = 0;
  143.  
  144.     STATX(ftag);
  145.     return file;
  146. }
  147.  
  148. /*
  149.     Print the status of a stream.
  150. */
  151. static char *
  152. io_cvt_status(int status)
  153. {
  154.     SL_DISABLE();
  155.  
  156.     switch(status) {
  157.     case IO_NULL:    return "IO_NULL";
  158.     case IO_CLOSED:    return "IO_CLOSED";
  159.     case IO_INPUT:    return "IO_INPUT";
  160.     case IO_OUTPUT:    return "IO_OUTPUT";
  161.     case IO_EOF:    return "IO_EOF";
  162.     default:        return "Bad file status";
  163.     }
  164. }
  165.  
  166. /*
  167.     Return the length of an open file or -1L.
  168. */
  169. long
  170. io_length(io_file * file)
  171. {
  172.     FTAG("io_length");
  173.     long value = -1;
  174.     STATB(ftag);
  175.     ASSERT(file);
  176.  
  177.     /* Seek to the end of the file. */
  178.     if (fseek(file -> io_file_file, 0, SEEK_END) != 0) {
  179.         goto error;
  180.     }
  181.  
  182.     /* Get the value. */
  183.     value = ftell(file -> io_file_file);
  184.     if (value == -1) {
  185.         goto error;
  186.     }
  187.  
  188.     /* Seek to the start of the file. */
  189.     fseek(file -> io_file_file, 0, SEEK_SET);
  190.  
  191. error:
  192. done:
  193.     TRACEPX(ftag,
  194.         es(file -> io_file_path_name); eblank();
  195.         eret(); elong(value); enl());
  196.     return value;
  197. }
  198.  
  199. /*
  200.     Open the file for reading only.
  201.     Return a pointer to the file stuct or NULL.
  202. */
  203. io_file *
  204. io_open(char * path_name, bool cant_flag, bool text_flag)
  205. {
  206.     FTAG("io_open");
  207.     FILE * os_file = NULL;
  208.     io_file * file = NULL;
  209.     STATB(ftag);
  210.     ASSERT(path_name);
  211.  
  212.     if (path_name[0] == '\0') {
  213.         if (cant_flag) {
  214.             err_error1("io_open: NULL file name");
  215.         }
  216.         goto done;
  217.     }
  218.  
  219.     os_file = fopen(path_name, text_flag ? "r" : "rb");
  220.     if (os_file == NULL) {
  221.         if (cant_flag) {
  222.             err_error2("Can not open ", path_name);
  223.         }
  224.         goto done;
  225.     }
  226.  
  227.     file = io_alloc(sizeof(io_file));
  228.  
  229.     file -> io_file_path_name = path_name;
  230.     file -> io_file_file = os_file;
  231.     file -> io_file_status = IO_INPUT;
  232.     file -> io_file_buffer = NULL;
  233.     file -> io_file_pointer = NULL;
  234.     file -> io_file_count = 0;
  235.     file -> io_file_bufsize = 0;
  236.  
  237. done:
  238.     STATX(ftag);
  239.     return file;
  240. }
  241.  
  242. /*
  243.     Read the indicated number of bytes into the buffer.
  244.     
  245.     Return the number of bytes read.
  246. */
  247. long 
  248. io_read (io_file * file, void * buffer, long n)
  249. {
  250.     FTAG("io_read");
  251.     STATB(ftag);
  252.     ASSERT(file && buffer && n);
  253.     
  254.     n = fread(buffer, 1, n, file -> io_file_file);
  255.     
  256.     STATX(ftag);
  257.     return n;
  258. }
  259.  
  260.  
  261. /*
  262.     Read an entire file into a buffer.
  263.     Add one byte at end for a possible added newline.
  264. */
  265. io_mem_block *
  266. io_read_all(char * path_name, bool cant_flag, bool text_flag)
  267. {
  268.     return io_read_pad_all(path_name, 0, ' ', 0, ' ', cant_flag, text_flag);
  269. }
  270.  
  271. /*
  272.     Read an entire file into a padded buffer.
  273.     Add one byte at end for a possible added newline.
  274. */
  275.  
  276. io_mem_block *
  277. io_read_pad_all(
  278.     char * path_name,
  279.     int lead_pad, char lead_char,
  280.     int trail_pad, char trail_char,
  281.     bool cant_flag, bool text_flag)
  282. {
  283.     FTAG("io_read_pad_all");
  284.     register long            length = 0;            /* Length of file in bytes. */
  285.     register char *            buffer = NULL;
  286.     register io_file *        file = NULL;
  287.     register io_mem_block *    result = NULL;
  288.     STATB(ftag);
  289.     
  290.     file = io_open(path_name, cant_flag, text_flag);
  291.     if (file == NULL) {
  292.         goto error;
  293.     }
  294.     
  295.     length = io_length(file);
  296.     if (length == -1L) {
  297.         goto error;
  298.     }
  299.         
  300.     /* mem_freep points to the buffer so it can be deallocated later. */
  301.     obj_new_macro(buffer, length+lead_pad+trail_pad+1, "io read all buf");
  302.     {        
  303.         long n = fread(buffer + lead_pad, 1, length, file -> io_file_file);
  304.         io_read_chars += n;
  305.         io_close(file);
  306.         if (n != length) {
  307.             goto error;
  308.         }
  309.     }
  310.  
  311.     /*
  312.         Fill in the leading and trailing fields.
  313.     */
  314.     {
  315.         register int i;
  316.         
  317.         for (i = 0; i < lead_pad; i++) {
  318.             buffer[i] = lead_char;
  319.         }
  320.         
  321.         for (i = 0; i < trail_pad; i++) {
  322.             buffer [length + lead_pad + i] = trail_char;
  323.         }
  324.     }
  325.     
  326.     /*
  327.         End the buffer with a zero byte.
  328.     */
  329.     buffer[length + lead_pad + trail_pad] = '\0';
  330.     
  331.     obj_new_macro(result, sizeof(io_mem_block), "io_mem_block");
  332.  
  333.     result -> mem_start = buffer + lead_pad;
  334.     result -> mem_length = length;
  335.     result -> mem_freep = buffer;
  336.     
  337.     TRACEPX(ftag,
  338.         es(path_name); enl();
  339.         es("mem_start: "); eptr(buffer+lead_pad);
  340.         es(" mem_length: "); elong(length);
  341.         es(" mem_freep: "); eptr(buffer);
  342.         enl());
  343.     
  344.     return result;
  345.  
  346. error:
  347.     TRACEPX(ftag, es("not found: "); es(path_name); enl());
  348.     return NULL;
  349. }
  350.  
  351. /*
  352.     Remove (delete) the named file.
  353.     It should be close.
  354. */
  355. void
  356. io_remove(char * file_name)
  357. {
  358.     FTAG("io_remove");
  359.     STATB(ftag);
  360.     
  361.     remove(file_name);
  362.     
  363.     STATX(ftag);
  364. }
  365.  
  366. /*
  367.     Rename a file.
  368. */
  369. void
  370. io_rename(char * old_name, char * new_name)
  371. {
  372.     rename(old_name, new_name);
  373. }
  374.  
  375. /*
  376.     Seek to the indicated byte of the file.
  377.     
  378.     Return IO_SEEK_OK if all went well.
  379. */
  380. int
  381. io_seek (io_file * file, long offset)
  382. {
  383.     ASSERT(file);
  384.     return fseek(file -> io_file_file, offset, SEEK_SET);
  385. }
  386.  
  387. /*
  388.     Print an io_file node.
  389. */
  390. void
  391. io_show_file(io_file * file)
  392. {
  393.     FTAG("io_show_file");
  394.     STATB(ftag);
  395.     ASSERT(file);
  396.  
  397.     #ifndef LIB_DONT_USE_ES
  398.  
  399.         ecnl();
  400.         es("file: "); es(file -> io_file_path_name);
  401.         es(" at: "); eptr(file);
  402.         es(" status: "); es(io_cvt_status(file -> io_file_status));
  403.     
  404.         ecnl();
  405.         es("buffer: "); eptr(file -> io_file_buffer);
  406.         es(" ptr: "); eptr(file -> io_file_pointer);
  407.         es(" count: "); elong(file -> io_file_count);
  408.         ecnl();
  409.  
  410.     #endif
  411.  
  412.     STATX(ftag);
  413. }
  414.  
  415. /*
  416.     Write file -> io_file_count bytes from file -> io_file_buffer.
  417.     Reset the file buffer pointer and counts after the write.
  418.     Return the number of bytes written.
  419. */
  420. long
  421. io_write(register io_file * file)
  422. {
  423.     FTAG("io_write");
  424.     size_t result = 0;
  425.     STATB(ftag);
  426.     ASSERT(file && file -> io_file_buffer && file -> io_file_count);
  427.  
  428.     result = fwrite(
  429.         file -> io_file_buffer,
  430.         1, file -> io_file_count,
  431.         file -> io_file_file);
  432.  
  433.     /*
  434.         We must not create *any* tracing output if es2os_flag is set!
  435.         (That would create a recursive call to io_write that would crash the stack.)
  436.     */
  437.     #if 0 /* old code */
  438.         if (!es2os_flag) {
  439.             TRACEP(ftag,
  440.                 es("file: "); eptr(file);
  441.                 es(" buffer: "); eptr(file -> io_file_buffer);
  442.                 es(" count: "); elong(file -> io_file_count); enl();
  443.                 eret(); elong(result); enl());
  444.         }
  445.     #endif
  446.  
  447.     /* Update these variables *after* printing the trace. */
  448.     file -> io_file_pointer = file -> io_file_buffer;
  449.     file -> io_file_count = 0;
  450.     io_write_chars += result;
  451.  
  452.     STATX(ftag);
  453.     return result;
  454. }
  455.  
  456. /*
  457.     Write n bytes from the buffer.
  458.     Return the number of bytes written.
  459. */
  460. long
  461. io_write_buffer(register io_file * file, void * buffer, long n)
  462. {
  463.     FTAG("io_write");
  464.     size_t result = 0;
  465.     STATB(ftag);
  466.     ASSERT(file);
  467.  
  468.     result = fwrite(buffer, 1, n, file -> io_file_file);
  469.  
  470.     /*
  471.         We must not create *any* tracing output if es2os_flag is set!
  472.         (That would create a recursive call to io_write that would crash the stack.)
  473.     */
  474.     #if 0 /* old code */
  475.         if (!es2os_flag) {
  476.             TRACEP(ftag,
  477.                 es("file: "); eptr(file);
  478.                 es(" buffer: "); eptr(file -> io_file_buffer);
  479.                 es(" count: "); elong(file -> io_file_count); enl();
  480.                 eret(); elong(result); enl());
  481.         }
  482.     #endif
  483.  
  484.     io_write_chars += result;
  485.  
  486.     STATX(ftag);
  487.     return result;
  488. }
  489.